class Schedule(object):
    def __init__(self):
        self.__scheduleImp = ScheduleImp()

    @staticmethod
    def newLevel0Task(imm, logFile):
        return ScheduleImp.newLevel0Task(imm, logFile)
    @staticmethod
    def newCompactTask(ssts):
        return ScheduleImp.newCompactTask(ssts)

    def pushBack(self, task):
        return self.__scheduleImp.pushBack(task)

    def popFront(self):
        return self.__scheduleImp.popFront()

    def clean(self):
        return self.__scheduleImp.clean()

    def start(self):
        self.__scheduleImp.start()

    def stop(self):
        self.__scheduleImp.stop()
    


import threading
import time
class ScheduleImp(object):
    class Task(object):
        def __init__(self, isInfinite=False):
            self.__isInfinite = isInfinite

        def run(self):
            pass

        def isInfinite(self):
            return self.__isInfinite

        def cancel(self):
            pass

    class Level0TaskImp(Task):
        def __init__(self, imm, logFile):
            super(ScheduleImp.Level0TaskImp, self).__init__()
            self.__imm = imm
            self.__logFile = logFile

        def run(self):
            if self.__imm is not None:
                self.__imm.getWriter().write()

            if self.__logFile is not None:
                self.__logFile.close()
                self.__logFile.delete()

            print("Level0TaskImp:: imm:[%d], logFile:[%d]" %(id(self.__imm), id(self.__logFile)))
            time.sleep(0.1)

        def cancel(self):
            print("Level0TaskImp:: cancel")

    class CompactTaskImp(Task):
        def __init__(self, ssts):
            super(ScheduleImp.CompactTaskImp, self).__init__(True)
            self.__ssts = ssts

        def run(self):
            time.sleep(0.1)
            print("CompactTaskImp:: ssts:%d" % id(self.__ssts))

        def cancel(self):
            print("CompactTaskImp::cancel")

    @staticmethod
    def newLevel0Task(imm, logFile):
        return ScheduleImp.Level0TaskImp(imm, logFile) 
    @staticmethod
    def newCompactTask(ssts):
        return ScheduleImp.CompactTaskImp(ssts)

    @staticmethod 
    def run(args):
        if len(args) > 0:
            this = args[0]
            this.run()
        #end if


    def __init__(self):
        self.__stop = False
        self.__tasks = []
        self.__lock = threading.Lock()
        self.__thread = threading.Thread(target=ScheduleImp.run, args=(self,))

    def pushBack(self, task):
        self.__lock.acquire()
        self.__tasks.append(task)
        self.__lock.release()

    def popFront(self):
        self.__lock.acquire()
        if len(self.__tasks) > 0:
            task = self.__tasks[0]
            del self.__tasks[0]
            self.__lock.release()
            return task
        self.__lock.release()
        return None

    def clean(self):
        self.__lock.acquire()
        for t in self.__tasks:
            t.cancel()
        self.__tasks = []
        self.__lock.release()


    def __canStop(self):
        self.__lock.acquire()
        stop = self.__stop and len(self.__tasks) == 0
        self.__lock.release()
        return stop == True

    def __isStoping(self):
        self.__lock.acquire()
        stop = self.__stop
        self.__lock.release()
        return stop == True
    

    def start(self):
        self.__thread.start()

    def run(self):
        while True:
            if self.__canStop():
                break;
            
            task = self.popFront()
            if task is None:
                time.sleep(0.5) #10ms
                print("sleep 10ms")
                continue

            task.run()

            if task.isInfinite() == True and not self.__isStoping():
                self.pushBack(task)
            #end if
        #end while
        print("exit quit")
        self.clean()

    def stop(self):
        self.__lock.acquire()
        self.__stop = True
        self.__lock.release()

        self.__thread.join()
        pass


import unittest
class TestSchedule(unittest.TestCase):
    def test(self):
        s = Schedule()
        s.pushBack(Schedule.newCompactTask(None))
        s.pushBack(Schedule.newLevel0Task(None, None))
        s.start()
        time.sleep(2)
        s.stop()

if __name__ == "__main__":
    suite = unittest.TestSuite([
        unittest.TestLoader().loadTestsFromTestCase(TestSchedule), 
    ])
    unittest.TextTestRunner(verbosity=2).run(suite)
